package Thread;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;

public class ThreadDemo21 { //实现一个线程池
    static class Worker extends Thread {//使用这个类来描述工作线程是啥样的
        private BlockingQueue<Runnable> blo;//Worker这个线程需要从阻塞队列中获取任务过来执行

        //所以需要获取到这个阻塞队列的实例，这个阻塞队列里面就是每一个任务
        public Worker(BlockingQueue<Runnable> blo) {//通过构造方法这个阻塞队列的实例传递过来
            //让这个线程里面能够获取到整个阻塞队列，进而获取到里面的任务
            this.blo = blo;
        }

        @Override
        public void run() {
            try {
                while (!Thread.currentThread().isInterrupted()) {
                    Runnable command = blo.take();//当这个线程不被终止的情况下，就会一直在这个阻塞队列中获取任务过来执行
                    command.run();//这个线程一直在阻塞队列中获取到任务然后执行。
                }
            } catch (InterruptedException e) {
                System.out.println(("线程被结束"));
            }
        }
    }

    static class MyThreadPool {//这个就是代表一个线程池
        private BlockingQueue<Runnable> blo = new LinkedBlockingDeque<>();//这个阻塞队列用来存放每一个任务
        //Worker线程就从这个阻塞队列中取一些任务过来执行
        //这个顺序表用来组织若干个工作线程
        private List<Worker> list = new ArrayList<>();
        private static final int workcount = 10;//这个代表线程的指定个数，如果小于它，就新创建线程来作为工作线程

        //如果大于它，就不再创建
        //实现execute方法和shutdown方法
        public void execute(Runnable command) throws InterruptedException {//这个方法的作用就是将任务加到阻塞队列中，线程执行的时候
            if (list.size() < workcount) {
                Worker worker = new Worker(blo);//创建线程来执行任务
                worker.start();
                list.add(worker);//把这个线程加入到表中
            }
            //就是在这个阻塞队列中取任务
            blo.put(command);
        }

        public void shutdown() throws InterruptedException {
            //终止掉所有的线程，也就是依次调用每个线程的interrupt方法
            //只要调用这个方法，就会调用表中的每个线程的interrupt方法来中断他们。
            for (Worker worker : list) {//遍历数组，然后依次调用里面的线程的interrupt方法来中断
                worker.interrupt();//每个线程执行这个方法的时候，很有可能执行到一半被触发异常。由于不涉及阻塞操作，所以是把判断条件设置为true。所以需要等while循环执行一半才会终止线程
                //所以还需要一个jion操作去等待线程结束
            }
            for (Worker worker : list) {//还需要等待每个线程执行结束
                //从收到异常到线程结束，中间可能还需要执行一些逻辑，尤其是catch里面的代码
                //当shutdown结束之后，意味着所有的线程一定都结束了。
                worker.join();
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyThreadPool p = new MyThreadPool();
        p.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println(("我是你爸爸"));
            }
        });
    }
}